package com.gwthtml.samples.chatdemo.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.gwthtml.ui.client.EventFormPanel;
import com.gwthtml.ui.client.HtmlTextBox;
import com.gwthtml.ui.client.ModeSwitcher;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class ChatDemo implements EntryPoint {

	VerticalPanel mainPanel = new VerticalPanel();
	VerticalPanel chatWindow = new VerticalPanel();
	Grid chatControls = new Grid(3,2);
	ScrollPanel chatScrollPanel = new ScrollPanel();
	
	HtmlTextBox nickName = new HtmlTextBox();
	HtmlTextBox message = new HtmlTextBox();
	Button sendMessage = new Button("Send");
	Button refresh = new Button("Refresh");
	
	ChatServiceAsync chatService = (ChatServiceAsync) GWT.create(ChatService.class);

	AsyncCallback serviceCb = new AsyncCallback() {

		public void onFailure(Throwable caught) {
			Window.alert("Exception caught:" + caught);
		}

		public void onSuccess(Object result) {
			showMessages((ChatMessage[]) result);
			message.setText("");
		}
		
	};
	
	ChatMessage lastShown = null;
	
  /**
   * This is the entry point method.
   */
  public void onModuleLoad() {
	  // Set up Service
	  ((ServiceDefTarget) chatService).setServiceEntryPoint(GWT.getModuleBaseURL() + "ChatService");
	  
	  chatControls.setWidget(0, 0, new Label("Nick:"));
	  chatControls.setWidget(0, 1, nickName);
	  chatControls.setWidget(1, 0, new Label("Message:"));
	  chatControls.setWidget(1, 1, message);
	  chatControls.setText(2, 0, "");
	  chatControls.setWidget(2, 1, sendMessage);
	  chatControls.addStyleName("chat-ChatControls");
	  
	  sendMessage.addClickListener(new ClickListener() {

		public void onClick(Widget arg0) {
			sendMessage();			
		}
		  
	  });
	  
	  refresh.addClickListener(new ClickListener() {

			public void onClick(Widget arg0) {
				queryUpdate(null);			
			}	  
	  });
	  
	  chatScrollPanel.addStyleName("chat-ScrollPanel");
	  chatScrollPanel.add(chatWindow);
	  chatWindow.addStyleName("chat-ChatWindow");
	  chatWindow.setSpacing(2);
	  EventFormPanel evPanel = new EventFormPanel();
	  mainPanel.add(chatScrollPanel);
	  mainPanel.add(chatControls);
	  mainPanel.add(new ModeSwitcher());
	  mainPanel.addStyleName("chat-MainPanel");
	  evPanel.add(mainPanel);
	  RootPanel.get().add(evPanel);
	  // Separate refresh button into a new EventFormPanel
	  // This makes sure that the Send button is "clicked" as the default action
	  EventFormPanel refreshForm = new EventFormPanel();
	  refreshForm.add(refresh);
	  RootPanel.get().add(refreshForm);
	  queryUpdate(null); // Do an initial refresh to get the already sent messages.
}
  
  
  private void sendMessage() {
	  ChatMessage msg = new ChatMessage();
	  msg.setMessage(message.getText());
	  msg.setNick(nickName.getText());
	  queryUpdate(msg);
  }
  
  private void queryUpdate(ChatMessage msg) {
	  chatService.sendMessage(msg, lastShown != null ? lastShown.getSequenceNum() : -1, serviceCb);	  
  }
  
  private void showMessages(ChatMessage[] msgs) {
	  if (msgs == null) return;
	  
	  for (int i = 0; i < msgs.length; i++) {
		  if (lastShown != null) {
			  if (msgs[i].getSequenceNum() <= lastShown.getSequenceNum()) {
				  continue;
			  }
		  }
		  chatWindow.add(formatMessage(msgs[i]));
	  }
	  lastShown = msgs[msgs.length - 1];
  }


private Widget formatMessage(ChatMessage msg) {
	HorizontalPanel entry = new HorizontalPanel();
	entry.addStyleName("chat-Message");
	Label nick = new Label(msg.getNick() + ":");
	nick.addStyleName("NickName");
	Label message = new Label(msg.getMessage());
	message.addStyleName("Message");
	entry.add(nick); 
	entry.add(message);
	return entry;	  
}
}
